/*
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package main;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import java.util.prefs.Preferences;

import org.apache.log4j.Logger;

import server.IntelServerType;
import database.DBConnectionFactory;

/**
 * This class handles the loading and saving of bot settings
 * 
 * 
 */
public class SettingsHandler {

   /**
    * Loads the basic bot settings into the supplied BotSettings object
    * 
    * @param botSettings
    */
   public void loadBotSettings(final BotSettings botSettings) {
	  Connection con = null;
	  PreparedStatement ps = null;
	  ResultSet rs = null;
	  try {
		 Map<String, String> dbSettings = loadDBSettings();
		 botSettings.setDbHost(dbSettings.get("dbHost"));
		 botSettings.setDbName(dbSettings.get("dbName"));
		 botSettings.setDbUsername(dbSettings.get("dbUsername"));
		 botSettings.setDbPassword(dbSettings.get("dbPassword"));
		 if (botSettings.getDbHost() != null && botSettings.getDbName() != null && botSettings.getDbUsername() != null
			   && botSettings.getDbPassword() != null) {
			con = DBConnectionFactory.getConnectionHandler().getConnection();
			if (con != null && DBConnectionFactory.getConnectionHandler().connectionIsValid()) {
			   ps = con.prepareStatement("SELECT * FROM version WHERE id = 0");
			   rs = ps.executeQuery();

			   if (rs.next()) {
				  botSettings.setBotVersion(rs.getInt("botversion"));
				  botSettings.setReleaseVersion(rs.getString("releaseversion"));
			   }

			   try {
				  ps.close();
			   } catch (final Exception e) {
			   }

			   ps = con.prepareStatement("SELECT * FROM settings WHERE id = 0");
			   rs = ps.executeQuery();

			   if (rs.next()) {
				  botSettings.setIrcServer(rs.getString("ircserver"));
				  botSettings.setIrcPort(rs.getInt("ircport"));
				  botSettings.setIrcDelay(rs.getInt("ircdelay"));
				  botSettings.setBotNick(rs.getString("botnick"));
				  botSettings.setBotPassword(rs.getString("botpw"));
				  botSettings.setMainChannel(rs.getString("mainchannel"));
				  botSettings.setAdminChannel(rs.getString("adminchannel"));
				  botSettings.setAgeStart(rs.getTimestamp("agestart").getTime());
				  botSettings.setPasswordAuth(rs.getBoolean("passwordauth"));
				  botSettings.setKdLoc(rs.getString("kdloc"));
				  botSettings.setIntelPort(rs.getInt("intelport"));
				  botSettings.listenForIntel(rs.getBoolean("runintel"));
				  botSettings.setIntelServerType(IntelServerType.fromString(rs.getString("intelservertype")));
				  botSettings.setRPCServicePort(rs.getInt("rpcserviceport"));
				  botSettings.runRPCService(rs.getBoolean("runrpcservice"));
				  botSettings.setRPCServicePassword(rs.getString("rpcpassword"));
				  botSettings.setUsersMayRegister(rs.getBoolean("usersmayregister"));
				  botSettings.setLimitAdminCommands(rs.getBoolean("limitadmincommands"));
				  botSettings.setTickLength(rs.getInt("ticklength"));
				  botSettings.setCommandPrefix(rs.getString("commandprefix"));
			   }

			   try {
				  ps.close();
			   } catch (final Exception e) {
			   }

			   ps = con.prepareStatement("SELECT * FROM smssettings WHERE id = 0");
			   rs = ps.executeQuery();

			   if (rs.next()) {
				  botSettings.setSmsSMTP(rs.getString("server"));
				  botSettings.setSmsUser(rs.getString("username"));
				  botSettings.setSmsPassword(rs.getString("password"));
				  botSettings.setSmsPort(rs.getInt("port"));
			   }

			   try {
				  ps.close();
			   } catch (final Exception e) {
			   }

			   ps = con.prepareStatement("SELECT * FROM google");
			   rs = ps.executeQuery();

			   if (rs.next()) {
				  botSettings.setGoogleAPIKey(rs.getString("apikey"));
			   }
			}
		 }
	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			rs.close();
		 } catch (final Exception e) {
		 }
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
   }

   /**
    * Loads and returns the database settings
    * 
    * @return
    */
   public Map<String, String> loadDBSettings() {
	  Map<String, String> out = new HashMap<String, String>();
	  BufferedReader br = null;
	  try {
		 br = new BufferedReader(new FileReader("settings.txt"));
		 String line;
		 while ((line = br.readLine()) != null) {
			String[] split = line.split("=");
			if (split.length == 2 && !"".equals(split[1])) {
			   out.put(split[0].trim(), split[1].trim());
			}
		 }
	  } catch (FileNotFoundException e) {
		 updateFromOldPropertiesSystem();
		 out = loadDBSettings();
	  } catch (IOException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			br.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Saves the basic bot settings
    * 
    * @return
    */
   public boolean saveBaseSettings() {
	  Connection con = null;
	  PreparedStatement ps = null;
	  boolean out = false;
	  try {
		 con = DBConnectionFactory.getConnectionHandler().getConnection();

		 ps = con.prepareStatement("DELETE FROM settings");
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = con.prepareStatement("INSERT INTO settings VALUES(0,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
		 ps.setString(1, Main.getBotSettings().getIrcServer());
		 ps.setString(2, Main.getBotSettings().getBotNick());
		 ps.setString(3, Main.getBotSettings().getBotPassword());
		 ps.setString(4, Main.getBotSettings().getMainChannel()
			   + ("".equals(Main.getBotSettings().getMainChannelPw()) ? "" : " " + Main.getBotSettings().getMainChannelPw()));
		 ps.setString(5, Main.getBotSettings().getAdminChannel()
			   + ("".equals(Main.getBotSettings().getAdminChannelPw()) ? "" : " " + Main.getBotSettings().getAdminChannelPw()));
		 ps.setTimestamp(6, new Timestamp(Main.getBotSettings().getAgeStart()));
		 ps.setBoolean(7, Main.getBotSettings().requirePasswordAuth());
		 ps.setString(8, Main.getBotSettings().getKdLoc());
		 ps.setInt(9, Main.getBotSettings().getIntelPort());
		 ps.setBoolean(10, Main.getBotSettings().listenForIntel());
		 ps.setString(11, Main.getBotSettings().getIntelServerType().toString());
		 ps.setInt(12, Main.getBotSettings().getRpcServicePort());
		 ps.setBoolean(13, Main.getBotSettings().runRPCService());
		 ps.setString(14, Main.getBotSettings().getRPCPassword());
		 ps.setBoolean(15, Main.getBotSettings().usersMayRegister());
		 ps.setBoolean(16, Main.getBotSettings().limitAdminCommands());
		 ps.setInt(17, Main.getBotSettings().getTickLength());
		 ps.setString(18, Main.getBotSettings().getCommandPrefix());
		 ps.setInt(19, Main.getBotSettings().getIrcPort());
		 ps.setInt(20, Main.getBotSettings().getIrcDelay());
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = con.prepareStatement("DELETE FROM smssettings");
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = con.prepareStatement("INSERT INTO smssettings VALUES(0,?,?,?,?)");
		 ps.setString(1, Main.getBotSettings().getSmsSMTP());
		 ps.setString(2, Main.getBotSettings().getSmsUser());
		 ps.setString(3, Main.getBotSettings().getSmsPassword());
		 ps.setInt(4, Main.getBotSettings().getSmsPort());
		 ps.executeUpdate();

		 if (!CommonMethods.kdExists("(" + Main.getBotSettings().getKdLoc() + ")")) {
			CommonMethods.addDefaultKD("(" + Main.getBotSettings().getKdLoc() + ")");
		 }

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = con.prepareStatement("DELETE FROM google");
		 ps.executeUpdate();

		 try {
			ps.close();
		 } catch (final Exception e) {
		 }

		 ps = con.prepareStatement("INSERT INTO google VALUES(?)");
		 ps.setString(1, Main.getBotSettings().getGoogleAPIKey());
		 ps.executeUpdate();

		 out = true;

	  } catch (final SQLException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			ps.close();
		 } catch (final Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Saves the database access settings
    * 
    * @param dbHost
    * @param dbName
    * @param dbUser
    * @param dbPassword
    * @return
    */
   public boolean saveDBSettings(final String dbHost, final String dbName, final String dbUser, final String dbPassword) {
	  BufferedWriter bw = null;
	  boolean out = false;
	  try {
		 bw = new BufferedWriter(new FileWriter("settings.txt"));
		 bw.write("dbHost=" + dbHost + "\n");
		 bw.write("dbName=" + dbName + "\n");
		 bw.write("dbUsername=" + dbUser + "\n");
		 bw.write("dbPassword=" + dbPassword + "\n");
		 bw.flush();
		 out = true;
	  } catch (IOException e) {
		 Logger.getLogger("Error").error("", e);
	  } finally {
		 try {
			bw.close();
		 } catch (Exception e) {
		 }
	  }
	  return out;
   }

   /**
    * Updates from the old system of storing database settings in Java Preferences, to storing them in a text file instead
    * 
    * @return
    */
   public boolean updateFromOldPropertiesSystem() {
	  Preferences prefs = Preferences.userNodeForPackage(getClass());
	  boolean out = saveDBSettings(prefs.get("dbHost", ""), prefs.get("dbName", ""), prefs.get("dbUsername", ""),
			prefs.get("dbPassword", ""));
	  prefs.remove("dbHost");
	  prefs.remove("dbName");
	  prefs.remove("dbUsername");
	  prefs.remove("dbPassword");
	  return out;
   }
}
